#region Apache License
//
// Licensed to the Apache Software Foundation (ASF) under one or more 
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership. 
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with 
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion



using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;

using IPSim.GUI.Devices;

namespace IPSim.GUI
{
    public class DeviceCollection : CollectionBase
    {
        #region Members

        public  const int   maxSize = 100;
        private Point       location = new Point(0,0);
        private Size        size = new Size(0, 0);

        #endregion

        #region Methods

        internal DeviceCollection(): base() 
        { 
        }


        internal virtual int Add(BaseDevice device)
        {
            CalcWindowLocation(device);
            CalcWindowSize(device);
            return InnerList.Add(device);
        }

        public bool Contains(BaseDevice device)
        {
            return InnerList.Contains(device);
        }

        public int IndexOf(BaseDevice device)
        {
            return InnerList.IndexOf(device);
        }

        internal void Insert(int index, BaseDevice device)
        {
            CalcWindowLocation(device);
            CalcWindowSize(device);
            InnerList.Insert(index, device);
        }

        internal void Remove(BaseDevice device)
        {
            // First check if device is BaseLinkDevice and disconnect it
            if (device is BaseLinkDevice)
            {
                BaseLinkDevice link = device as BaseLinkDevice;
                link.Connector1.DisconnectLink(link);
                link.Connector2.DisconnectLink(link);
            }
            else
            {
                foreach (ConnectorDevice conn in device.Connectors)
                {
                    if (conn.IsConnected)
                        Remove(conn.ConnectedLink);
                }
            }
            InnerList.Remove(device);
            CalcWindow();
        }

        // new is for overrided method hiding
        internal new void Clear()
        {
            InnerList.Clear();
            CalcWindow();
        }

        internal void ChangeIndex(int i, int y)
        {
            object tmp = InnerList[y];
            InnerList[y] = InnerList[i];
            InnerList[i] = tmp;
        }


        internal void CalcWindow()
        {
            location.X = maxSize;
            location.Y = maxSize;
            size.Width = 0;
            size.Height = 0;
            foreach (BaseDevice device in this)
            {
                CalcWindowLocation(device);
            }

            foreach (BaseDevice device in this)
            {
                CalcWindowSize(device);
            }
        }

        internal void CalcWindowLocation(BaseDevice device)
        {
            Point deviceLocation = device.Location;

            if (deviceLocation.X < location.X)
                location.X = deviceLocation.X;

            if (deviceLocation.Y < location.Y)
                location.Y = deviceLocation.Y;
        }

        internal void CalcWindowSize(BaseDevice device)
        {
            int val;

            Point deviceLocation = device.Location;
            Size deviceSize = device.Size;

            val = (deviceLocation.X + deviceSize.Width) - location.X;
            if (val > size.Width)
                size.Width = val;

            val = (deviceLocation.Y + deviceSize.Height) - location.Y;
            if (val > size.Height)
                size.Height = val;
        }

        #endregion

        #region Properties

        public BaseDevice this[int item]
        {
            get
            {
                return (BaseDevice)InnerList[item];
            }
        }

        internal Point Location
        {
            get
            {
                return location;
            }
        }

        internal Size Size
        {
            get
            {
                return size;
            }
        }

        #endregion

    }
}
